package com.demo.arch.datapulsedemo.v2_pipeline.steps;

import com.demo.arch.datapulsedemo.common.NotificationRecipient;
import com.demo.arch.datapulsedemo.v2_pipeline.core.PipelineContext;
import com.demo.arch.datapulsedemo.v2_pipeline.core.StepExecutionException;
import com.demo.arch.datapulsedemo.v2_pipeline.core.StepHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.List;

/**
 * 步骤4：邮件发送处理器
 * 
 * 职责：
 * - 构建邮件内容
 * - 发送给所有接收人
 * - 统计发送结果
 * 
 * @author DataPulse Team
 */
@Slf4j
@Component
public class EmailSendStepHandler implements StepHandler {

  @Override
  public String getName() {
    return "邮件发送";
  }

  @Override
  public int getOrder() {
    return 4;
  }

  @Override
  public void handle(PipelineContext context) throws StepExecutionException {
    log.info(">>> [{}] 开始执行", getName());

    try {
      // 构建邮件内容
      String subject = buildEmailSubject(context);
      String content = buildEmailContent(context);

      context.setEmailSubject(subject);
      context.setEmailContent(content);

      log.info("邮件主题: {}", subject);
      log.info("邮件内容:\n{}", content);

      // 初始化成功邮箱集合（如果为空）
      if (context.getSuccessEmails() == null) {
        context.setSuccessEmails(new HashSet<>());
      }

      // 发送给所有接收人
      List<NotificationRecipient> recipients = context.getRecipients();
      int successCount = 0;
      int failCount = 0;

      for (NotificationRecipient recipient : recipients) {
        String email = recipient.getEmail();

        // 幂等性检查：已发送成功的跳过
        if (context.getSuccessEmails().contains(email)) {
          log.info("邮件已发送给: {}, 跳过", email);
          successCount++;
          continue;
        }

        try {
          sendEmail(recipient, subject, content);

          // 记录成功
          context.getSuccessEmails().add(email);
          successCount++;

          log.info("邮件发送成功: {}", email);

        } catch (Exception e) {
          log.error("发送给 {} 失败: {}", recipient.getName(), e.getMessage());
          failCount++;
        }
      }

      // 保存统计结果
      context.setEmailSuccessCount(successCount);
      context.setEmailFailCount(failCount);

      log.info(">>> [{}] 完成，成功 {} 人，失败 {} 人",
          getName(), successCount, failCount);

      // 如果有失败，抛出异常（触发重试）
      if (failCount > 0) {
        throw new StepExecutionException(
            getName(),
            String.format("邮件发送部分失败：成功%d个，失败%d个", successCount, failCount));
      }

    } catch (Exception e) {
      log.error(">>> [{}] 执行失败", getName(), e);
      throw new StepExecutionException(getName(), "邮件发送失败", e);
    }
  }

  @Override
  public boolean shouldExecute(PipelineContext context) {
    // 幂等性检查：如果所有邮件都已发送，跳过执行
    if (context.getSuccessEmails() != null &&
        context.getRecipients() != null &&
        context.getSuccessEmails().size() == context.getRecipients().size()) {
      log.info(">>> [{}] 所有邮件已发送，跳过执行", getName());
      return false;
    }
    return true;
  }

  /**
   * 构建邮件主题
   */
  private String buildEmailSubject(PipelineContext context) {
    return String.format("[%s] 报表生成完成通知", context.getReportType());
  }

  /**
   * 构建邮件内容
   */
  private String buildEmailContent(PipelineContext context) {
    return String.format(
        """
            报表已生成完成！

            == 基本信息 ==
            报表类型: %s
            文件路径: %s
            数据条数: %d
            生成时间: %s

            请查收附件。
            """,
        context.getReportType(),
        context.getExcelFilePath(),
        context.getOrderData().size(),
        LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
  }

  /**
   * 发送邮件（模拟）
   */
  private void sendEmail(NotificationRecipient recipient, String subject, String content) {
    log.info("正在发送邮件给: {} ({}) - {}",
        recipient.getName(),
        recipient.getRole(),
        recipient.getEmail());

    // 模拟邮件发送
    try {
      Thread.sleep(30);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    }

    log.info("邮件发送成功: {} ({})",
        recipient.getName(),
        recipient.getType().getDescription());
  }
}
